package com.mj.mybatis;

import com.mj.domain.UserDO;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 马洁
 * @date 2020/9/18 - 11:37
 */
public class MyBatisInvocationHandlerImpl implements InvocationHandler {

    Connection connection;

    public MyBatisInvocationHandlerImpl(Connection connection) {
        this.connection = connection;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 解析XML
        // 把方法对应的语句和返回值封装成为SQLBean
        // 放入map，根据方法获取
        // Map<Method, SQLBean>

        // 1. 取出对应的sqlbean
        // sqlbean = map.get(method);

        Class<?> returnType = method.getReturnType();
        boolean isList = false;

        if (returnType.isInterface() && returnType == List.class) {
            isList = true;
        }


        Object resObj = null;

        SqlBean sqlBean = getSqlBeanByMethod(method);

        ResultSet resultSet = query(getSql(sqlBean));

        if (isList) {
            List<Object> list = new ArrayList<>();
            while (resultSet.next()) {
                resObj = sqlBean.getReturnType().getConstructor().newInstance();
                setFieldValue(resObj, resultSet, sqlBean.getReturnType());
                list.add(resObj);
            }

            return list;
        }

        return resObj;
    }

    private void setFieldValue(Object obj, ResultSet resultSet, Class<?> returnType) throws SQLException, IllegalAccessException {
        for (Field field : returnType.getDeclaredFields()) {
            field.setAccessible(true);

            if (field.getType() == Integer.class) {
                field.set(obj, resultSet.getInt(field.getName()));
            } else if (field.getType() == String.class) {
                field.set(obj, resultSet.getString(field.getName()));
            }
        }
    }

    public PreparedStatement getSql(SqlBean sqlBean) throws SQLException {
        return connection.prepareStatement(sqlBean.getSql());
    }

    public ResultSet query(PreparedStatement preparedStatement) throws SQLException {
        return preparedStatement.executeQuery();
    }

    public SqlBean getSqlBeanByMethod(Method method) {
        return new SqlBean("select * from user", UserDO.class);
    }
}
